/**
 * helper_impl.c - 辅助工具插件函数实现
 *
 * 提供各种辅助工具插件中使用的函数实现
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <pthread.h>
#include <openssl/ssl.h>
#include <linux/limits.h>

#include "helper_functions.h"
#include "../../include/hook_framework.h"

/* 全局统计数据 */
static pthread_mutex_t stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned long total_connections = 0;
static unsigned long total_bytes_sent = 0;
static unsigned long total_bytes_received = 0;
static unsigned long total_ssl_bytes = 0;
static unsigned long total_file_bytes = 0;

/* 敏感域名列表 */
static const char* sensitive_domains[] = {
    "example.evil.com",
    "malware.example.org",
    "suspicious.domain.net",
    NULL
};

/**
 * 解析IP地址为主机名
 */
int helper_reverse_dns(const char* ip_str, char* hostname, size_t hostname_size) {
    if (!ip_str || !hostname || hostname_size == 0) return 0;
    
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    
    if (inet_pton(AF_INET, ip_str, &(addr.sin_addr)) <= 0) {
        return 0;
    }
    
    char host[NI_MAXHOST] = {0};
    if (getnameinfo((struct sockaddr*)&addr, sizeof(addr),
                   host, sizeof(host), NULL, 0, NI_NAMEREQD) == 0) {
        strncpy(hostname, host, hostname_size - 1);
        hostname[hostname_size - 1] = '\0';
        return 1;
    }
    
    return 0;
}

/**
 * 检查是否为敏感域名
 */
int is_sensitive_domain(const char* hostname) {
    if (!hostname) return 0;
    
    for (int i = 0; sensitive_domains[i] != NULL; i++) {
        if (strstr(hostname, sensitive_domains[i])) {
            return 1;
        }
    }
    
    return 0;
}

/**
 * 更新连接数统计
 */
void update_connections(void) {
    pthread_mutex_lock(&stats_mutex);
    total_connections++;
    pthread_mutex_unlock(&stats_mutex);
}

/**
 * 检查数据内容
 */
void helper_inspect_data(const char* prefix, const void* data, size_t size) {
    if (!prefix || !data || size == 0) return;
    
    log_message(LOG_INFO, "%s: %zu 字节数据", prefix, size);
    
    /* 可以选择打印前N个字节的十六进制表示 */
    const unsigned char* bytes = (const unsigned char*)data;
    char hex_buffer[128] = {0};
    size_t print_size = size < 16 ? size : 16;
    
    for (size_t i = 0; i < print_size; i++) {
        sprintf(hex_buffer + (i * 3), "%02x ", bytes[i]);
    }
    
    log_message(LOG_DEBUG, "数据前缀: %s", hex_buffer);
}

/**
 * 更新发送字节统计
 */
void update_bytes_sent(size_t bytes) {
    pthread_mutex_lock(&stats_mutex);
    total_bytes_sent += bytes;
    pthread_mutex_unlock(&stats_mutex);
}

/**
 * 更新接收字节统计
 */
void update_bytes_received(size_t bytes) {
    pthread_mutex_lock(&stats_mutex);
    total_bytes_received += bytes;
    pthread_mutex_unlock(&stats_mutex);
}

/**
 * 更新SSL字节统计
 */
void update_ssl_bytes(size_t bytes) {
    pthread_mutex_lock(&stats_mutex);
    total_ssl_bytes += bytes;
    pthread_mutex_unlock(&stats_mutex);
}

/**
 * 检查文件描述符是否为常规文件
 */
int helper_is_regular_file(int fd) {
    struct stat st;
    if (fstat(fd, &st) != 0) return 0;
    return S_ISREG(st.st_mode);
}

/**
 * 获取文件描述符对应的路径
 */
int helper_get_fd_path(int fd, char* path, size_t path_size) {
    if (fd < 0 || !path || path_size == 0) return 0;
    
    char proc_path[64];
    snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", fd);
    
    ssize_t len = readlink(proc_path, path, path_size - 1);
    if (len < 0) return 0;
    
    path[len] = '\0';
    return 1;
}

/**
 * 更新文件读取统计
 */
void update_file_read(size_t bytes) {
    pthread_mutex_lock(&stats_mutex);
    total_file_bytes += bytes;
    pthread_mutex_unlock(&stats_mutex);
}

/**
 * 获取当前统计信息
 */
void get_statistics(unsigned long* connections, unsigned long* bytes_sent,
                  unsigned long* bytes_received, unsigned long* ssl_bytes,
                  unsigned long* file_bytes) {
    pthread_mutex_lock(&stats_mutex);
    if (connections) *connections = total_connections;
    if (bytes_sent) *bytes_sent = total_bytes_sent;
    if (bytes_received) *bytes_received = total_bytes_received;
    if (ssl_bytes) *ssl_bytes = total_ssl_bytes;
    if (file_bytes) *file_bytes = total_file_bytes;
    pthread_mutex_unlock(&stats_mutex);
} 